package com.mrzhou.rabbit.producer;

import com.mrzhou.common.constant.MQConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.UUID;

/**
 * 邮件发送到rabbitMQ
 */
@Component
@Slf4j
public class EmailProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 如果消息没有到exchange,则confirm回调,ack=false
     * 如果消息到达exchange,则confirm回调,ack=true
     * exchange到queue成功,则不回调return
     * exchange到queue失败,则回调return(需设置mandatory=true,否则不回回调,消息就丢了)
     */
    private final RabbitTemplate.ConfirmCallback confirmCallback =  (correlationData, ack, cause) -> {
        // 如消息发送失败, 应该通过其他方式发送, 目前思路使用redis订阅方式来处理发送失败的消息
        if(!ack) {
            log.error("消息发送失败：correlationData: {},cause: {}", correlationData, cause);
        }
    };
    private final RabbitTemplate.ReturnCallback returnCallback = (message, replyCode, replyText, exchange, routingKey) -> {
        // 如消息发送失败, 应该通过其他方式发送, 目前思路使用redis订阅方式来处理发送失败的消息
        log.error("消息丢失: message: {}, exchange: {},routeKey: {},replyCode: {},replyText: {}", message, replyCode, replyText, exchange, routingKey);
    };

    /**
     * 发送消息
     * @param message 消息内容
     */
    public void send(Object message) {
        // 构建回调返回的数据
        CorrelationData correlationData = new CorrelationData();
        correlationData.setId(UUID.randomUUID().toString()); // 生成消息ID
        rabbitTemplate.setConfirmCallback(confirmCallback); // 设置发送成功的回调方式
        rabbitTemplate.setReturnCallback(returnCallback);
        rabbitTemplate.convertAndSend(MQConstant.EMAIL_MSG_EXCHANGE, MQConstant.EMAIL_MSG_ROUTINGKEY, message, correlationData);
    }

}
